<template>
  <div
    ref="popoverWrapperRef"
    class="toolbar-popover-wrapper"
    tabindex="0"
    @blur="handleTriggerBlur"
  >
    <!-- 按钮触发器 -->
    <ToolbarButton
      ref="popoverTriggerRef"
      v-bind="buttonAttrs"
      :class="{ 'is-popover-open': isPopoverVisible }"
      @click="handlePopoverTriggerClick"
      @mouseenter="handlePopoverMouseEnter"
      @mouseleave="handlePopoverMouseLeave"
    >
      <slot></slot>
    </ToolbarButton>

    <!-- Popover 内容 -->
    <teleport to="body">
      <div
        v-if="isPopoverVisible"
        ref="popoverContentRef"
        :class="['toolbar-popover-content', popperClass]"
        :style="[
          popoverFloatingStyles,
          typeof popperStyle === 'object' ? popperStyle : {},
          {
            width: typeof width === 'number' ? `${width}px` : width,
          },
        ]"
        @click.stop
        @mouseenter="handlePopoverMouseEnter"
        @mouseleave="handlePopoverMouseLeave"
      >
        <slot name="popover"></slot>
      </div>
    </teleport>
  </div>
</template>

<script setup lang="ts">
import {
  computed,
  onBeforeUnmount,
  onMounted,
  ref,
  watch,
  nextTick,
  useAttrs,
} from "vue";
import { useFloating, offset, flip, shift, autoUpdate } from "@floating-ui/vue";
import type { PopoverProps } from "./button.types";
import ToolbarButton from "./Button.vue";
import {
  closeAllToolbarPopups,
  onCloseAllToolbarPopups,
  type CloseAllToolbarPopupsEventDetail,
} from "./utils/toolbarPopupManager";

defineOptions({
  inheritAttrs: false,
  name: "ToolbarPopover",
});

const props = withDefaults(defineProps<PopoverProps>(), {
  placement: "bottom",
  width: 200,
  trigger: "click",
  disabled: false,
  popperClass: "",
  popperStyle: () => ({}),
});

const emit = defineEmits<{
  (e: "show"): void;
  (e: "before-enter"): void;
  (e: "after-enter"): void;
  (e: "hide"): void;
  (e: "before-leave"): void;
  (e: "after-leave"): void;
}>();

const attrs = useAttrs();
const popoverTriggerRef = ref<InstanceType<typeof ToolbarButton>>();
const popoverContentRef = ref<HTMLDivElement>();
const buttonElementRef = ref<HTMLElement>();
const popoverWrapperRef = ref<HTMLDivElement>();

// 提取按钮相关的属性
const buttonAttrs = computed(() => ({
  icon: getAttrValue<string>("icon"),
  title: getAttrValue<string>("title"),
  largeIcon: getAttrValue<boolean>("largeIcon", false),
  active: getAttrValue<boolean>("active", false),
  disabled: props.disabled,
  hideText: getAttrValue<boolean>("hideText", true),
  round: getAttrValue<boolean>("round", false),
  circle: getAttrValue<boolean>("circle", false),
}));

// 从 attrs 中获取属性值
const getAttrValue = <T>(key: string, defaultValue?: T): T | undefined => {
  // 先尝试直接获取
  if (attrs[key] !== undefined) {
    return attrs[key] as T;
  }
  // 再尝试驼峰转短横线格式
  const kebabKey = camelToKebab(key);
  if (attrs[kebabKey] !== undefined) {
    return attrs[kebabKey] as T;
  }
  return defaultValue;
};

// 驼峰转短横线
const camelToKebab = (str: string): string => {
  return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
};

// Popover 状态和定位
const isPopoverVisible = ref(false);

// 获取按钮元素引用
watch(
  () => popoverTriggerRef.value,
  (buttonInstance) => {
    if (buttonInstance) {
      nextTick(() => {
        // 从暴露的 buttonRef 获取 DOM 元素
        const exposed = buttonInstance as any;
        if (exposed?.buttonRef) {
          buttonElementRef.value = exposed.buttonRef as HTMLElement;
        }
      });
    }
  },
  { immediate: true }
);

// 使用 floating-ui 定位 Popover
const { floatingStyles: popoverFloatingStyles } = useFloating(
  buttonElementRef,
  popoverContentRef,
  {
    placement: props.placement as any,
    middleware: [offset(8), flip(), shift({ padding: 5 })],
    whileElementsMounted: autoUpdate,
    open: computed(() => isPopoverVisible.value),
  }
);

// 监听关闭所有弹窗的事件
const handleCloseAllPopups = (
  event: CustomEvent<CloseAllToolbarPopupsEventDetail>
) => {
  const { currentInstance, excludeTypes } = event.detail;
  // 如果当前实例不是当前 Popover，或者被排除，则关闭
  if (
    currentInstance !== popoverWrapperRef.value &&
    !excludeTypes?.includes("popover") &&
    isPopoverVisible.value
  ) {
    handlePopoverHide();
  }
};

let cleanupPopupListener: (() => void) | null = null;

// 在组件挂载时添加事件监听
onMounted(() => {
  cleanupPopupListener = onCloseAllToolbarPopups(handleCloseAllPopups);
});

// 在组件卸载时移除事件监听
onBeforeUnmount(() => {
  if (cleanupPopupListener) {
    cleanupPopupListener();
    cleanupPopupListener = null;
  }
});

// Popover 处理
const handlePopoverTriggerClick = (event?: MouseEvent) => {
  if (props.disabled) return;
  event?.stopPropagation();

  if (props.trigger === "click") {
    isPopoverVisible.value = !isPopoverVisible.value;
    if (isPopoverVisible.value) {
      // 打开时，先关闭所有其他弹窗
      closeAllToolbarPopups(popoverWrapperRef.value, "popover");
      emit("show");
      emit("before-enter");
      nextTick(() => {
        emit("after-enter");
      });
    } else {
      handlePopoverHide();
    }
  }
};

const handlePopoverMouseEnter = () => {
  if (props.trigger === "hover") {
    isPopoverVisible.value = true;
    emit("show");
    emit("before-enter");
    nextTick(() => {
      emit("after-enter");
    });
  }
};

const handlePopoverMouseLeave = () => {
  if (props.trigger === "hover") {
    handlePopoverHide();
  }
};

const handlePopoverHide = () => {
  emit("before-leave");
  emit("hide");
  nextTick(() => {
    emit("after-leave");
    isPopoverVisible.value = false;
  });
};

// 处理触发器失焦事件
const handleTriggerBlur = (event: FocusEvent) => {
  // 如果焦点移到了 popover 内容区域，不关闭
  const relatedTarget = event.relatedTarget as Node | null;
  if (relatedTarget && popoverContentRef.value?.contains(relatedTarget)) {
    return;
  }

  // 如果焦点移到了按钮内部，不关闭
  const buttonEl = popoverTriggerRef.value
    ? (popoverTriggerRef.value as any)?.buttonRef
    : null;
  if (relatedTarget && buttonEl && buttonEl.contains(relatedTarget)) {
    return;
  }

  // 失焦时立即关闭 popover
  if (isPopoverVisible.value && props.trigger === "click") {
    handlePopoverHide();
  }
};

// 点击外部关闭 Popover
const handleClickOutsidePopover = (event: MouseEvent) => {
  const target = event.target as Node;

  // 获取按钮元素
  const buttonEl = popoverTriggerRef.value
    ? (popoverTriggerRef.value as any)?.buttonRef
    : null;

  if (
    (buttonEl && buttonEl.contains(target)) ||
    popoverContentRef.value?.contains(target)
  ) {
    return;
  }
  if (isPopoverVisible.value && props.trigger === "click") {
    handlePopoverHide();
  }
};

watch(isPopoverVisible, (visible) => {
  if (visible && props.trigger === "click") {
    nextTick(() => {
      document.addEventListener("click", handleClickOutsidePopover);
    });
  } else {
    document.removeEventListener("click", handleClickOutsidePopover);
  }
});

onBeforeUnmount(() => {
  if (isPopoverVisible.value) {
    isPopoverVisible.value = false;
  }
  document.removeEventListener("click", handleClickOutsidePopover);
});
</script>

<style scoped>
.toolbar-popover-wrapper {
  display: inline-block;
  margin: 0 2px;
}
</style>

<style>
.toolbar-popover-content {
  padding: var(--editor-tooltip-content-padding);
  background: var(--editor-color-white);
  border: 1px solid var(--editor-border-color-light);
  border-radius: var(--editor-radius-medium);
  box-shadow: var(--editor-shadow);
  color: var(--editor-text-color);
  font-size: var(--editor-font-size);
  z-index: 9999;
}

.toolbar-popover-content.popover-as-menu {
  border: 1px solid var(--editor-border-color-light);
  box-shadow: var(--editor-shadow);
  padding: 6px 0;
}
</style>
